#pragma once
#include <fmt/color.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <fmt/ranges.h>
#include <spdlog/spdlog.h>
#include <stdio.h>

///0000000000000000000000000000000000000000000000000 console color
#define MY_CLR_FG_BL_STRING "\033[0m\033[38;2;0;255;255m"
#define MY_CLR_FG_RESET_STRING "\033[0m"
#define MY_CLR_FG_BL (::std::cout << MY_CLR_FG_BL_STRING)
#define MY_CLR_FG_RESET (::std::cout << MY_CLR_FG_RESET_STRING)
// #define MY_FLUSH_STD_OUT_ std::fflush(stdout)
#define MY_FLUSH_STD_OUT_

///0000000000000000000000000000000000000000000000000 format pring
///====================================== format string
#define MYFMT ::fmt::format
///====================================== terminal colored info
#define TCINFO(...)                    \
    ::fmt::print(MY_CLR_FG_BL_STRING); \
    ::fmt::print(__VA_ARGS__);         \
    ::fmt::print(MY_CLR_FG_RESET_STRING);
///====================================== plain info with linefeed
#define TMINFOLN(...)          \
    ::fmt::print(__VA_ARGS__); \
    ::fmt::print("\n");

///====================================== Decorated info
//::fmt::print("''''''''''''''''''''''''''''''''''''''''''");
//::fmt::print(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;");
#define _TM_DECORATED_INFOLN(...)                               \
    ::fmt::print("``````````````````````````````````````````"); \
    ::fmt::print(__VA_ARGS__);                                  \
    ::fmt::print("\n");

///00000000000000000000000000000000000000000000000000000000 spdlog macros
#define LINFO(...) ::spdlog::info(__VA_ARGS__);
#define LDEBUG(...) ::spdlog::debug(__VA_ARGS__);
#define LWARN(...) ::spdlog::warn(__VA_ARGS__);
#define LERROR(...) ::spdlog::error(__VA_ARGS__);

///00000000000000000000000000000000000000000000000000000000 2nd macros
//-------------------------------------- Debug info
#define DINFOLN LINFO
// #define DINFOLN(...) // 定义为空, 则不输出 debug 信息

///00000000000000000000000000000000000000000000000000000000 G4 macros
#define MYG4TID(tid) const auto tid = G4Threading::G4GetThreadId();

///00000000000000000000000000000000000000000000000000000000
//=== guard, 确保在每个 thread 只执行一次
#define TCALLONCE1(printed_ctor)            \
    thread_local bool printed_ctor = false; \
    if (!printed_ctor)                      \
    {                                       \
        printed_ctor = true;
#define TCALLONCE2 }